package org.microframework.cloud.auth.handler;

import java.io.IOException;

import org.microframework.base.core.domain.R;
import org.microframework.base.core.util.IpUtil;
import org.microframework.base.feign.logs.RemoteLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AccountExpiredException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

/**
 * 认证失败处理器
 * 等保要求：记录认证失败日志，提供友好的错误信息
 */
@Slf4j
@Component
public class AuthenticationFailureHandlerImpl implements AuthenticationFailureHandler {

    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired(required = false)
    private RemoteLogService loginLogService;

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException exception) throws IOException, ServletException {
        
        // 获取用户名
        String username = request.getParameter("username");
        
        // 根据异常类型返回不同的错误信息
        String errorMessage;
        if (exception instanceof BadCredentialsException) {
            errorMessage = "用户名或密码错误";
        } else if (exception instanceof LockedException) {
            errorMessage = "账号已被锁定";
        } else if (exception instanceof DisabledException) {
            errorMessage = "账号已被禁用";
        } else if (exception instanceof AccountExpiredException) {
            errorMessage = "账号已过期";
        } else {
            errorMessage = "认证失败: " + exception.getMessage();
        }
        
        // 记录登录失败日志
        if (loginLogService != null) {
            // 获取IP地址
            String ip = IpUtil.getIpAddr(request);
            // 获取用户代理信息
            String userAgent = request.getHeader("User-Agent");
            String browser = "未知";
            String os = "未知";
            if (userAgent != null) {
                // 简单提取浏览器和操作系统信息
                if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
                    browser = "IE";
                } else if (userAgent.contains("Firefox")) {
                    browser = "Firefox";
                } else if (userAgent.contains("Chrome")) {
                    browser = "Chrome";
                } else if (userAgent.contains("Safari")) {
                    browser = "Safari";
                } else if (userAgent.contains("Opera")) {
                    browser = "Opera";
                }
                
                if (userAgent.contains("Windows")) {
                    os = "Windows";
                } else if (userAgent.contains("Mac OS")) {
                    os = "Mac OS";
                } else if (userAgent.contains("Linux")) {
                    os = "Linux";
                } else if (userAgent.contains("Android")) {
                    os = "Android";
                } else if (userAgent.contains("iOS")) {
                    os = "iOS";
                }
            }
            
            loginLogService.recordLoginFailure(username, errorMessage, ip, null, browser, os);
        }
        
        log.warn("用户[{}]登录失败: {}", username, errorMessage);
        
        // 返回认证失败信息
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding("UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(R.fail(HttpStatus.UNAUTHORIZED.value(), errorMessage)));
    }
} 